
#ifndef JVMDLLLOADER_H
#define JVMDLLLOADER_H

namespace Pan
{

    /**
     * @brief 表示 jvm.dll, 在析构函数中自动释放动态链接库
     */
    class JvmDll
    {
    public:
        friend class JvmDllLoader;

    protected:
        void *_handle; // dll句柄

    protected:
        JvmDll(void *handle = nullptr);

    public:
        JvmDll(JvmDll &&jvm_dll);
        ~JvmDll();

        void operator=(JvmDll &&jvm_dll);

    public:
        inline void *handle() { return this->_handle; }

    public:
        bool is_valid();
    };

    /****************************************************************/

    /**
     * @brief jvm.dll 动态链接库的加载器
     */
    class JvmDllLoader
    {

    public:
        /**
                 * @brief 检查一个文件是否存在
                 * @param filePath 文件名称
                 * @return 文件是否存在
                 */
        static bool checkFileExists(const wchar_t *filePath);

    public:
        /**
                 * @brief 将一个绝对路径转换为父路径
                 * @param fullPath 传入绝对路径
                 */
        static void changeToParentPath(wchar_t *fullPath);

    public:
        /**
                 * @brief 尝试以一个二进制目录加载jvm.dll
                 * @param directory 目录
                 * @return jvm.dll的模块句柄, 加载失败返回NULL
                 */
        static JvmDll tryLoadWithBinaryDirectory(const wchar_t *directory);

    public:
        /**
                 * @brief 从jdkHome或jreHome尝试加载jvm.dll
                 * @param javaHome jdkHome或者jreHome
                 * @return jvm.dll的模块句柄, 失败返回NULL
                 */
        static JvmDll tryLoadWithJavaHome(const wchar_t *javaHome);

    public:
        /**
         * @brief 尝试以一个含有JavaHome的目录加载jvm.dll
         * @param directory 传入目录
         * @return jvm.dll的模块句柄, 失败返回NULL
         */
        static JvmDll tryLoadWithDirectoryHasJavaHome(const wchar_t *directory);

    private:
        /**
          * @brief 内置的字符串复制函数
          * @param to 目标字符串
          * @param from 源字符串
          */
        static void stringCopy(wchar_t *to, const wchar_t *from);

    private:
        JvmDllLoader();

    private:
        ~JvmDllLoader();

    public:
        /**
         * @brief 加载jvm.dll
         * @return jvm.dll的模块句柄, 失败返回NULL
         */
        static JvmDll loadJvmDll();

    public:
        /**
         * @brief 通过path环境变量指定的目录中加载jvm.dll
           * @return jvm.dll的模块句柄, 失败返回NULL
         */
        static JvmDll loadJvmDll_pathEnv();

        /**
         * @brief 搜索程序目录的临近目录, 尝试加载jvm.dll
         * @return jvm.dll的模块句柄, 失败返回NULL
         */
    public:
        static JvmDll loadJvmDll_nearFolder();

        /**
         * @brief 在java的默认安装位置查找并加载
         * @return jvm.dll的模块句柄, 失败返回NULL
         */
    public:
        static JvmDll loadJvmDll_javaInstall();
    };
}

#endif // JVMDLLLOADER_H